<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4.0													  |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group								|
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license,	   |
// | that is bundled with this package in the file LICENSE, and is		|
// | available at through the world-wide-web at						   |
// | http://www.php.net/license/2_02.txt.								 |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to		  |
// | license@php.net so we can mail you a copy immediately.			   |
// +----------------------------------------------------------------------+
// | Author: Ron McClain <ron@humaniq.com>								|
// +----------------------------------------------------------------------+
//
// $Id: Object.php,v 1.1 2006/09/24 17:04:56 jamiesensei Exp $

require_once('HTML/QuickForm/Renderer.php');

/**
 * A concrete renderer for HTML_QuickForm, makes an object from form contents
 *
 * Based on HTML_Quickform_Renderer_Array code
 *
 * @access public
 */
class HTML_QuickForm_Renderer_Object extends HTML_QuickForm_Renderer
{
	/**
	 * The object being generated
	 * @var object $_obj
	 */
	var $_obj= null;

	/**
	 * Number of sections in the form (i.e. number of headers in it)
	 * @var integer $_sectionCount
	 */
	var $_sectionCount;

	/**
	* Current section number
	* @var integer $_currentSection
	*/
	var $_currentSection;

	/**
	* Object representing current group
	* @var object $_currentGroup
	*/
	var $_currentGroup = null;

	/**
	 * Class of Element Objects
	 * @var object $_elementType
	 */
	var $_elementType = 'QuickFormElement';

	/**
	* Additional style information for different elements  
	* @var array $_elementStyles
	*/
	var $_elementStyles = array();

	/**
	* true: collect all hidden elements into string; false: process them as usual form elements
	* @var bool $_collectHidden
	*/
	var $_collectHidden = false;


	/**
	 * Constructor
	 *
	 * @param collecthidden bool	true: collect all hidden elements
	 * @access public
	 */
	function HTML_QuickForm_Renderer_Object($collecthidden = false) 
	{
		$this->HTML_QuickForm_Renderer();
		$this->_collectHidden = $collecthidden;
		$this->_obj = new QuickformForm;
	}

	/**
	 * Return the rendered Object
	 * @access public
	 */
	function toObject() 
	{
		return $this->_obj;
	}

	/**
	 * Set the class of the form elements.  Defaults to QuickformElement.
	 * @param type string   Name of element class
	 * @access public
	 */
	function setElementType($type)
	{
		$this->_elementType = $type;
	}

	function startForm(&$form) 
	{
		$this->_obj->frozen = $form->isFrozen();
		$this->_obj->javascript = $form->getValidationScript();
		$this->_obj->attributes = $form->getAttributes(true);
		$this->_obj->requirednote = $form->getRequiredNote();
		$this->_obj->errors = new StdClass;

		if($this->_collectHidden) {
			$this->_obj->hidden = '';
		}
		$this->_elementIdx = 1;
		$this->_currentSection = null;
		$this->_sectionCount = 0;
	} // end func startForm

	function renderHeader(&$header) 
	{
		$hobj = new StdClass;
		$hobj->header = $header->toHtml();
		$this->_obj->sections[$this->_sectionCount] = $hobj;
		$this->_currentSection = $this->_sectionCount++;
	}

	function renderElement(&$element, $required, $error) 
	{
		$elObj = $this->_elementToObject($element, $required, $error);
		if(!empty($error)) {
			$name = $elObj->name;
			$this->_obj->errors->$name = $error;
		}
		$this->_storeObject($elObj);
	} // end func renderElement

	function renderHidden(&$element)
	{
		if($this->_collectHidden) {
			$this->_obj->hidden .= $element->toHtml() . "\n";
		} else {
			$this->renderElement($element, false, null);
		}
	} //end func renderHidden

	function startGroup(&$group, $required, $error) 
	{
		$this->_currentGroup = $this->_elementToObject($group, $required, $error);
		if(!empty($error)) {
			$name = $this->_currentGroup->name;
			$this->_obj->errors->$name = $error;
		}
	} // end func startGroup

	function finishGroup(&$group) 
	{
		$this->_storeObject($this->_currentGroup);
		$this->_currentGroup = null;
	} // end func finishGroup

	/**
	 * Creates an object representing an element
	 *
	 * @access private
	 * @param element object	An HTML_QuickForm_element object
	 * @param required bool		 Whether an element is required
	 * @param error string	Error associated with the element
	 * @return object
	 */
	function _elementToObject(&$element, $required, $error) 
	{
		if($this->_elementType) {
			$ret = new $this->_elementType;
		}
		$ret->name = $element->getName();
		$ret->value = $element->getValue();
		$ret->type = $element->getType();
		$ret->frozen = $element->isFrozen();
		$labels = $element->getLabel();
		if (is_array($labels)) {
			$ret->label = array_shift($labels);
			foreach ($labels as $key => $label) {
				$key = is_int($key)? $key + 2: $key;
				$ret->{'label_' . $key} = $label;
			}
		} else {
			$ret->label = $labels;
		}
		$ret->required = $required;
		$ret->error = $error;

		if(isset($this->_elementStyles[$ret->name])) {
			$ret->style = $this->_elementStyles[$ret->name];
			$ret->styleTemplate = "styles/". $ret->style .".html";
		}
		if($ret->type == 'group') {
			$ret->separator = $element->_separator;
			$ret->elements = array();
		} else {
			$ret->html = $element->toHtml();
		}
		return $ret;
	}

	/** 
	 * Stores an object representation of an element in the form array
	 *
	 * @access private
	 * @param elObj object	 Object representation of an element
	 * @return void
	 */
	function _storeObject($elObj) 
	{
		$name = $elObj->name;
		if(is_object($this->_currentGroup) && $elObj->type != 'group') {
			$this->_currentGroup->elements[] = $elObj;
		} elseif (isset($this->_currentSection)) {
			$this->_obj->sections[$this->_currentSection]->elements[] = $elObj;
		} else {
			$this->_obj->elements[] = $elObj;
		}
	}

	function setElementStyle($elementName, $styleName = null)
	{
		if(is_array($elementName)) {
			$this->_elementStyles = array_merge($this->_elementStyles, $elementName);
		} else {
			$this->_elementStyles[$elementName] = $styleName;
		}
	}

} // end class HTML_QuickForm_Renderer_Object



/**
 * Convenience class for the form object passed to outputObject()
 * 
 * Eg.  
 * {form.outputJavaScript():h}
 * {form.outputHeader():h}
 *   <table>
 *	 <tr>
 *	   <td>{form.name.label:h}</td><td>{form.name.html:h}</td>
 *	 </tr>
 *   </table>
 * </form>
 */
class QuickformForm
{
   /**
	* Whether the form has been frozen
	* @var boolean $frozen
	*/
	var $frozen;

   /**
	* Javascript for client-side validation
	* @var string $javascript
	*/
	var $javascript;

   /**
	* Attributes for form tag
	* @var string $attributes
	*/
	var $attributes;

   /**
	* Note about required elements
	* @var string $requirednote
	*/
	var $requirednote;

   /**
	* Collected html of all hidden variables
	* @var string $hidden
	*/
	var $hidden;

   /**
	* Set if there were validation errors.  
	* StdClass object with element names for keys and their
	* error messages as values
	* @var object $errors
	*/
	var $errors;

   /**
	* Array of QuickformElementObject elements.  If there are headers in the form
	* this will be empty and the elements will be in the 
	* separate sections
	* @var array $elements
	*/
	var $elements;

   /**
	* Array of sections contained in the document
	* @var array $sections
	*/
	var $sections;

   /**
	* Output &lt;form&gt; header
	* {form.outputHeader():h} 
	* @return string	&lt;form attributes&gt;
	*/
	function outputHeader()
	{
		return "<form " . $this->attributes . ">\n";
	}

   /**
	* Output form javascript
	* {form.outputJavaScript():h}
	* @return string	Javascript
	*/
	function outputJavaScript()
	{
		return $this->javascript;
	}
} // end class QuickformForm


/**
 * Convenience class describing a form element.
 * The properties defined here will be available from 
 * your flexy templates by referencing
 * {form.zip.label:h}, {form.zip.html:h}, etc.
 */
class QuickformElement
{
	/**
	 * Element name
	 * @var string $name
	 */
	var $name;

	/**
	 * Element value
	 * @var mixed $value
	 */
	var $value;

	/**
	 * Type of element
	 * @var string $type
	 */
	var $type;

	/**
	 * Whether the element is frozen
	 * @var boolean $frozen
	 */
	var $frozen;

	/**
	 * Label for the element
	 * @var string $label
	 */
	var $label;

	/**
	 * Whether element is required
	 * @var boolean $required
	 */
	var $required;

	/**
	 * Error associated with the element
	 * @var string $error
	 */
	var $error;

	/**
	 * Some information about element style
	 * @var string $style
	 */
	var $style;

	/**
	 * HTML for the element
	 * @var string $html
	 */
	var $html;

	/**
	 * If element is a group, the group separator
	 * @var mixed $separator
	 */
	var $separator;

	/**
	 * If element is a group, an array of subelements
	 * @var array $elements
	 */
	var $elements;

	function isType($type)
	{
		return ($this->type == $type);
	}

	function notFrozen()
	{
		return !$this->frozen;
	}

	function isButton()
	{
		return ($this->type == "submit" || $this->type == "reset");
	}


   /**
	* XXX: why does it use Flexy when all other stuff here does not depend on it?
	*/
	function outputStyle()
	{
		ob_start();
		HTML_Template_Flexy::staticQuickTemplate('styles/' . $this->style . '.html', $this);
		$ret = ob_get_contents();
		ob_end_clean();
		return $ret;
	}
} // end class QuickformElement
?>
